using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace DA.AnimGraph.Editor {
    public class ClickManipulator : PointerManipulator {

        public Vector2 lastMousePosition { get; private set; }
        protected bool active { get; set; }
        private int m_ActivePointerId = -1;
        public event Action<EventBase> clickedWithEventInfo;

        public ClickManipulator(Action<EventBase> handler, MouseButton mouseButton, int clickCount) {
            this.clickedWithEventInfo = handler;
            base.activators.Add(new ManipulatorActivationFilter {
                button = mouseButton,
                clickCount = clickCount,
            });
        }

        protected override void RegisterCallbacksOnTarget() {
            base.target.RegisterCallback<MouseDownEvent>(OnMouseDown);
            base.target.RegisterCallback<MouseMoveEvent>(OnMouseMove);
            base.target.RegisterCallback<MouseUpEvent>(OnMouseUp);
            base.target.RegisterCallback<MouseCaptureOutEvent>(OnMouseCaptureOut);
        }

        protected override void UnregisterCallbacksFromTarget() {
            base.target.UnregisterCallback<MouseDownEvent>(OnMouseDown);
            base.target.UnregisterCallback<MouseMoveEvent>(OnMouseMove);
            base.target.UnregisterCallback<MouseUpEvent>(OnMouseUp);
            base.target.UnregisterCallback<MouseCaptureOutEvent>(OnMouseCaptureOut);
        }

        private void OnMouseDown(MouseDownEvent evt) {
            if (CanStartManipulation(evt)) {
                ProcessDownEvent(evt, evt.localMousePosition, PointerId.mousePointerId);
            }
        }

        private void OnMouseMove(MouseMoveEvent evt) {
            if (active) {
                ProcessMoveEvent(evt, evt.localMousePosition);
            }
        }

        private void OnMouseUp(MouseUpEvent evt) {
            if (active && CanStopManipulation(evt)) {
                ProcessUpEvent(evt, evt.localMousePosition, PointerId.mousePointerId);
            }
        }

        private void OnMouseCaptureOut(MouseCaptureOutEvent evt) {
            if (active) {
                ProcessCancelEvent(evt, PointerId.mousePointerId);
            }
        }

        private void ProcessDownEvent(MouseDownEvent evt, Vector3 localPosition, int pointerId) {
            active = true;
            m_ActivePointerId = pointerId;
            lastMousePosition = localPosition;
            evt.StopImmediatePropagation();
        }

        private void ProcessUpEvent(MouseUpEvent evt, Vector2 localMousePosition, int mousePointerId) {
            active = false;
            m_ActivePointerId = -1;
            Invoke(evt);
            evt.StopPropagation();
        }
        private void ProcessMoveEvent(MouseMoveEvent evt, Vector2 localMousePosition) {
            lastMousePosition = localMousePosition;
            evt.StopPropagation();
        }
        private void ProcessCancelEvent(MouseCaptureOutEvent evt, int mousePointerId) {
            active = false;
            m_ActivePointerId = -1;
            evt.StopPropagation();
        }
        protected void Invoke(EventBase evt) {
            this.clickedWithEventInfo?.Invoke(evt);
        }

    }
}
